/**
 * @filename:JobServiceImpl 2022-9-28
 * @project Wonder Java前后台分离框架  1.1.0
 * Copyright(c) 2022 Wonder Co. Ltd. 
 * All right reserved. 
 */
package com.wonder.admin.service.impl;

import com.wonder.admin.domain.Job;
import com.wonder.admin.mapper.JobDao;
import com.wonder.admin.service.JobService;
import com.wonder.admin.request.JobRequest;
import com.wonder.common.utils.StringUtils;
import com.wonder.job.constant.ScheduleConstants;
import com.wonder.job.utils.CronUtils;
import com.wonder.job.utils.ScheduleUtils;
import com.wonder.common.utils.Convert;
import com.wonder.common.utils.MessageUtils;
import com.wonder.common.common.AjaxMap;
import com.wonder.common.config.WonderConfig;
import com.wonder.common.exception.job.TaskException;

import java.util.Map;

import javax.annotation.PostConstruct;

import java.util.HashMap;
import java.util.List;

import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

/**   
 * @Description:TODO(任务管理服务实现)
 *
 * @version: 1.1.0
 * @author: Wonder
 * 
 */
@Service
public class JobServiceImpl  extends ServiceImpl<JobDao, Job> implements JobService  {

	
	@Autowired
	Scheduler scheduler;
	
	@Value("${wonder.module}")
	String module;
	
	
	
	 /**
     * 项目启动时，初始化定时器 
     * 主要是防止手动修改数据库导致未同步到定时任务处理（注：不能手动修改数据库ID和任务组名，否则会导致脏数据）
     */
   @PostConstruct
    public void init() throws SchedulerException, TaskException
    {
        List<Job> jobList = this.list(new QueryWrapper<Job>().eq("module",module));
        for (Job job : jobList)
        {
            updateSchedulerJob(job, job.getJob_group());
        }
    }
    /**
     * 验证任务管理信息
     * 
     * @param Job信息
     * @return 结果
     */
    @Override
    public String validate(Job job,String type){
    
    
       return "";
    }
    
    /**
	 * Description:任务管理分页返回
	 * @request:检索条件
	 * @page：分页参数
	 * @return:分页记录
	 */
	@Override 
	public IPage<Job> selectList(JobRequest request, Page<Job> page){
	    QueryWrapper<Job> queryWrapper = new QueryWrapper<>();
	    
	    if (null != request.getJob_id()) {
	       queryWrapper.eq("job_id", request.getJob_id());
	      }               
             
        if (StringUtils.hasText(request.getJob_name())) {
			    queryWrapper.eq("job_name", request.getJob_name());
		    } 
             
    
	    if(StringUtils.hasText(request.getOrder()) && StringUtils.hasText(request.getSort())){
	        if(request.getOrder().equals("desc")) {
	        		queryWrapper.orderByDesc(request.getSort());
	        }else {
	        		queryWrapper.orderByAsc(request.getSort());
	        }
	    }else{
			queryWrapper.orderByDesc("job_id");	
		}    		
		Page<Job> selectPage = this.baseMapper.selectPage(page, queryWrapper);

		return selectPage;
      }
	
	/**
     * 暂停任务
     * 
     * @param job 调度信息
     */
    @Override
    @Transactional
    public boolean pauseJob(Job job) throws SchedulerException
    {
        Long jobId = job.getJob_id();
        job=this.getById(jobId);
        String jobGroup = job.getJob_group();
        job.setStatus(0);
        boolean rows = this.updateById(job);
        if (rows  && job.getModule().equals(module))
        {
            scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
        return rows;
    }

    /**
     * 恢复任务
     * 
     * @param job 调度信息
     */
    @Override
    @Transactional
    public boolean resumeJob(Job job) throws SchedulerException
    {
        Long jobId = job.getJob_id();
        job=this.getById(jobId);
        String jobGroup = job.getJob_group();
        
        job.setStatus(1);
        boolean rows = this.updateById(job);
        if (rows  && job.getModule().equals(module))
        {
            scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
        return rows;
    }

    /**
     * 删除任务后，所对应的trigger也将被删除
     * 
     * @param job 调度信息
     */
    @Override
    @Transactional
    public boolean deleteJob(Job job) throws SchedulerException
    {
        Long jobId = job.getJob_id();
        job=this.getById(jobId);
        String jobGroup = job.getJob_group();
        boolean rows = this.removeById(jobId);
        if (rows)
        {
            scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
        return rows;
    }

    /**
     * 批量删除调度信息
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    @Transactional
    public void deleteJobByIds(String ids) throws SchedulerException
    {
        Long[] jobIds = Convert.toLongArray(ids);
        for (Long jobId : jobIds)
        {
            Job job = this.getById(jobId);
            deleteJob(job);
        }
    }

    /**
     * 任务调度状态修改
     * 
     * @param job 调度信息
     */
    @Override
    @Transactional
    public boolean changeStatus(Job job) throws SchedulerException
    {
        boolean rows = false;
        int status = job.getStatus();
        if (status==1)
        {
            rows = resumeJob(job);
        }
        else if (status==0)
        {
            rows = pauseJob(job);
        }
        return rows;
    }

    /**
     * 立即运行任务
     * 
     * @param job 调度信息
     * @throws TaskException 
     */
    @Override
    @Transactional
    public void run(Job job) throws SchedulerException, TaskException
    {
        Long jobId = job.getJob_id();
        job=this.getById(jobId);
        if(!job.getModule().equals(module)) return;//Not running job, if not for this module
        String jobGroup = job.getJob_group();
        Job properties = this.getById(job.getJob_id());
        // 参数
        JobDataMap dataMap = new JobDataMap();
        dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
        if(scheduler.checkExists(jobKey)) {
        	scheduler.triggerJob(jobKey, dataMap);
        }else {
        	 ScheduleUtils.createScheduleJob(scheduler, job);
        	 scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap);
        }
    }

    /**
     * 新增任务
     * 
     * @param job 调度信息 调度信息
     */
    @Override
    @Transactional
    public int insertJob(Job job) throws SchedulerException, TaskException
    {
        job.setStatus(0);
        int rows = this.baseMapper.insert(job);
        if (rows > 0 && job.getModule().equals(module))
        {
            ScheduleUtils.createScheduleJob(scheduler, job);
        }
        return rows;
    }

    /**
     * 更新任务的时间表达式
     * 
     * @param job 调度信息
     */
    @Override
    @Transactional
    public int updateJob(Job job) throws SchedulerException, TaskException
    {
        Job properties =this.getById(job.getJob_id());
        int rows = this.baseMapper.updateById(job);
        if (rows > 0  && job.getModule().equals(module))
        {
            updateSchedulerJob(job, properties.getJob_group());
        }
        return rows;
    }

    /**
     * 更新任务
     * 
     * @param job 调度信息
     * @param jobGroup 任务组名
     */
    public void updateSchedulerJob(Job job, String jobGroup) throws SchedulerException, TaskException
    {
        Long jobId = job.getJob_id();
        // 判断是否存在
        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
        if (scheduler.checkExists(jobKey))
        {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        if(!job.getModule().equals(module)) return;//Not running job, if not for this module
        ScheduleUtils.createScheduleJob(scheduler, job);
    }

    /**
     * 校验cron表达式是否有效
     * 
     * @param cronExpression 表达式
     * @return 结果
     */
    @Override
    public boolean checkCronExpressionIsValid(String cronExpression)
    {
        return CronUtils.isValid(cronExpression);
    }
        
    
	
}